﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;

namespace luck
{
    /// <summary>
    /// 以随机数方式抽奖
    /// 人员名单和奖项设置都按一定格式编写在txt文件中,文件按要求命名后存放在可执行文件所在目录下
    /// 
    /// 创建: 2018-02-15 12:59 除夕
    /// 更新: 2018-03-11 17:19
    /// 作者: cikker
    /// 类版本: 0.1.0
    /// </summary>
    class luck
    {
        private string[] name_array = null;    // 人员名单字符串数组
        private string[] luck_set = null;      // 奖项设置缓存数组
        private string[] luck_data = null;     // 保存每个奖项的所有中奖名单
        private int a_index;                   // 当前奖项名称在luck_set数组中的索引
        private int b_index;                   // 当前奖项已抽名额
        private string name;                   // 当前最新确认抽中的某个人员名称

        private Random ran = null;             // 抽奖随机数种子

        int status = 0;                        // 抽奖启停标志变量
        Semaphore luck_lock_sema = null;       // 抽奖线程运行与阻塞的同步信号标志
        Thread lunck_t = null;

        public delegate void AlarmEventHandler(object sender, EventArgs e);    // 关于事件的委托
        public event AlarmEventHandler Alarm;                                  // 事件用于对外通知抽奖界面可以刷新所需显示的数据

        public luck()
        {
            // 读取奖项设置
            StreamReader sr_set = new StreamReader(System.Windows.Forms.Application.StartupPath + "\\set.txt");
            string res_set = sr_set.ReadToEnd();
            sr_set.Close();
            luck_set = Regex.Split(res_set, "\r\n", RegexOptions.IgnoreCase);       // 以回车换行拆分奖项设置

            // 读取人员名单
            StreamReader sr_name = new StreamReader(System.Windows.Forms.Application.StartupPath + "\\name.txt");
            string res_name = sr_name.ReadToEnd();
            sr_name.Close();
            name_array = Regex.Split(res_name, "\r\n", RegexOptions.IgnoreCase);    // 以回车换行拆分人员姓名 一行一个姓名

            // 初始化关键变量
            if (-1 == read_context()) 
            {
                new_context();
            }

            ran = new Random();            
        }

        private void new_context()
        {
            luck_data = new string[luck_set.Length / 2];      // 保存的字符串格式形如: [二等奖] aaa bbb
            int j = luck_set.Length / 2;
            for (int i = 0; i < j; i++)
            {
                luck_data[i] = "[" + luck_set[i * 2] + "]";
            }

            a_index = b_index = 0;     // 必须要初始化成0
        }

        private int read_context()
        {
            if (!File.Exists(System.Windows.Forms.Application.StartupPath + @"\context\index"))
            {
                return -1;
            }

            if (!File.Exists(System.Windows.Forms.Application.StartupPath + @"\context\res")) 
            {
                return -1;
            }

            // 读取a_index和b_index
            StreamReader sr_index = new StreamReader(System.Windows.Forms.Application.StartupPath + @"\context\index");
            string res_index = sr_index.ReadToEnd();
            sr_index.Close();
            string[] temp = Regex.Split(res_index, "&", RegexOptions.IgnoreCase);
            a_index = int.Parse(temp[0]);
            b_index = int.Parse(temp[1]);

            if ((a_index == luck_set.Length - 2) && (b_index == int.Parse(luck_set[luck_set.Length - 1])))
            {
                return -1;
            }

            // 读取luck_data数组内容
            StreamReader sr_res = new StreamReader(System.Windows.Forms.Application.StartupPath + @"\context\res");
            string res_res = sr_res.ReadToEnd();
            sr_res.Close();
            luck_data = Regex.Split(res_res, System.Environment.NewLine, RegexOptions.IgnoreCase);

            return 0;
        }

        /// <summary>
        /// 获取当前最新确认抽中的某个人员名称
        /// </summary>
        public string name_now
        {
            get
            {
                return name;
            }
        }

        /// <summary>
        /// 获取当前正在抽取的奖项名称
        /// 若返回"end"表示所有奖项已抽出即抽奖完全结束
        /// </summary>
        public string luck_now
        {
            get
            {
                if (a_index != -1)
                {
                    return luck_set[a_index];
                }
                else 
                {
                    return "end";
                }
               
            }
        }

        /// <summary>
        /// 获取当前奖项已中奖的所有人员名单
        /// </summary>
        public string luck_now_all_name
        {
            get
            {
                return luck_data[a_index / 2];
            }
        }

        /// <summary>
        /// 开始抽奖
        /// 抽奖线程将处于运行状态,由抽奖线程具体负责抽奖任务
        /// </summary>
        public void start()
        {
            if (a_index == -1)
            {
                return;
            }

            // 满足条件则当前奖项名额已全部抽出
            if (b_index == int.Parse(luck_set[a_index + 1]))
            {
                // 满足条件则全部奖项已抽完
                if (a_index == luck_set.Length - 2)
                {
                    a_index = -1;
                    return;
                }
                // 切换到下一个奖项
                else
                {
                    a_index += 2;
                    b_index = 0;
                }
            }

            if (luck_lock_sema == null)
            {
                luck_lock_sema = new Semaphore(0, 1);
            }

            if (lunck_t == null)
            {
                lunck_t = new Thread(luck_thread);
                lunck_t.Start();
            }

            status = 1;
            luck_lock_sema.Release();
        }

        /// <summary>
        /// 抽奖暂停
        /// 抽奖线程将处于停止状态
        /// </summary>
        public void stop()
        {
            status = 0;

            if (a_index == -1)
            {
                if (lunck_t != null)
                {
                    lunck_t.Abort();
                }
            }
        }

        /// <summary>
        /// 完全退出抽奖
        /// 抽奖线程退出,抽奖软件关闭时调用否则抽奖线程无法终止
        /// </summary>
        public void exit()
        {
            if (lunck_t != null)
            {
                lunck_t.Abort();
            }
        }

        /// <summary>
        /// 抽取一个准中奖人员
        /// </summary>
        /// <param name="res">中奖人员名称</param>
        /// <param name="ran_num">随机数结果值即人员名单中数组下标</param>
        private void luck_run(out string res, out int ran_num)
        {
            res = "";
            ran_num = -1;          

            if (name_array.Length > 0)
            {
                ran_num = ran.Next(0, name_array.Length);
                while (name_array[ran_num] == "-1")
                {
                    ran_num = ran.Next(0, name_array.Length);
                }

                res = name_array[ran_num].Trim();
            }
        }

        /// <summary>
        /// 确认准中奖人员中奖
        /// </summary>
        /// <param name="ran_num">传入luck_run方法输出的ran_num数值</param>
        private void luck_confirm(int ran_num)
        {
            // 记录该人员到中奖名单中
            int i = a_index / 2;
            luck_data[i] += " ";
            luck_data[i] += name_array[ran_num];

            // 标记该人员已中过奖
            name_array[ran_num] = "-1";

            ++b_index;

            // 保存运行时数据到文件中
            store_name();
            store_luck_data();
            store_index();
        }

        private void store_name()
        {
        }

        /// <summary>
        /// 保存目前所有的中奖结果即luck_data数组内容
        /// </summary>
        private void store_luck_data()
        {
            StreamWriter sw = new StreamWriter(System.Windows.Forms.Application.StartupPath + @"\context\res");

            string temp = "";
            for (int i = 0; i < luck_data.Length; i++)
            {
                temp += luck_data[i];
                temp += System.Environment.NewLine;   // 系统默认的换行字符串
            }
            sw.Write(temp);

            sw.Close();
        }

        /// <summary>
        /// 保存a_index和b_index的值
        /// </summary>
        private void store_index()
        {
            StreamWriter sw = new StreamWriter(System.Windows.Forms.Application.StartupPath +  @"\context\index");
            string contents = a_index.ToString() + "&" + b_index.ToString(); 
            sw.Write(contents);
            sw.Close();
        }

        /// <summary>
        /// 抽奖线程
        /// </summary>
        private void luck_thread()
        {
            int num;

            luck_lock_sema.WaitOne();    // 等待抽奖初次开始

            for (; ; )
            {
                luck_run(out name, out num);

                if (this.Alarm != null)
                {
                    this.Alarm(this, new EventArgs());   // 发出事件信号
                }

                // 抽奖处于暂停状态即确认抽出一个中奖名额 并需要等待继续抽奖信号
                if (status == 0)
                {
                    luck_confirm(num);
                    if (this.Alarm != null)
                    {
                        this.Alarm(this, new EventArgs());
                    }

                    luck_lock_sema.WaitOne();
                }
                else
                {
                    Thread.Sleep(100);
                }
            }
        }
    }
}
